use core::{
    cell::UnsafeCell,
    ffi::c_void,
    mem::MaybeUninit, slice
};

unsafe impl <const SIZE: usize> Send for AlignStore<SIZE> {}
unsafe impl <const SIZE: usize> Sync for AlignStore<SIZE> {}


#[repr(align(8))]
pub struct AlignStore<const SIZE: usize> {
    buf: [UnsafeCell<MaybeUninit<u8>>; SIZE],
}

impl<const SIZE: usize> AlignStore<SIZE> {
    const V: UnsafeCell<MaybeUninit<u8>> = UnsafeCell::new(MaybeUninit::uninit());

    #[inline(always)]
    pub const fn const_new() -> Self {
        Self {
            buf: [Self::V; SIZE],
        }
    }

    #[inline(always)]
    pub const fn raw_ptr(&self) -> *mut c_void {
        self.buf.as_ptr() as *mut c_void
    }

    #[inline(always)]
    pub const unsafe fn as_ptr(&self) -> *const u8 {
        self.buf.as_ptr() as _
    }

    pub unsafe fn as_mut_ptr(&self) -> *mut u8 {
        self.as_ptr() as _
    }

    pub unsafe fn as_mut_slice(&self) -> &mut[u8] {
        slice::from_raw_parts_mut(self.as_mut_ptr(), self.size())
    }

    pub unsafe fn as_slice(&self) -> &[u8] {
        slice::from_raw_parts(self.as_ptr(), self.size())
    }

    pub unsafe fn sub(&self, len: usize) -> &[u8] {
        slice::from_raw_parts(self.as_ptr(), len)
    }

    pub unsafe fn mut_sub(&self, len: usize) -> &mut [u8] {
        slice::from_raw_parts_mut(self.as_mut_ptr(), len)
    }

    #[inline(always)]
    pub const fn size(&self) -> usize {
        SIZE
    }
}
